<?php
namespace Icsoc\DataBundle\Model;

use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Class LocationModel
 *
 * @package Icsoc\DataBundle\Model
 */
class LocationModel extends BaseModel
{

    /** @var \Symfony\Component\DependencyInjection\Container */
    public $container;

    /**
     * @param ContainerInterface $container
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * 获取号码归属地
     *
     * @param string $phone
     *
     * @return array
     */
    public function getNumberloc($phone)
    {
        if (empty($phone)) {
            $ret = array(
                'code' => 401,
                'message' => '号码参数为空',
            );

            return $ret;
        }
        /** @var $db \Doctrine\DBAL\Connection */
        $db = $this->container->get("doctrine.dbal.sqlite_connection");
        /** @var \Symfony\Bridge\Monolog\Logger $logger */
        $logger = $this->container->get("logger");
        //非手机号码，固话直接返回对应信息
        if (!$this->checkPhoneIsMobileOrNot($phone)) {
            //首位号码为0表示号码带区号
            if (substr($phone, 0, 1) == '0') {
                //3位区号的固话
                if (substr($phone, 0, 3) == '010' || substr($phone, 0, 2) == '02') {
                    $realPhone = substr($phone, 3);
                    $code = substr($phone, 0, 3);
                } else {
                    //4位区号
                    $realPhone = substr($phone, 4);
                    $code = substr($phone, 0, 4);
                }
            } else {
                //首位不为0表示不带区号
                $realPhone = $phone;
                $code = '';
            }

            //查询区号对应的城市信息
            $info = $db->fetchAssoc(
                "SELECT num,code,city,cardtype FROM location WHERE code = :code ",
                array('code' => $code)
            );
            if (empty($info)) {
                $city = '';
            } else {
                $city = empty($info['city']) ? '' : $info['city'];
            }
            $ret = array(
                'code' => 200,
                'message' => 'ok',
                'data' => array(
                    'num' => '',
                    'code' => $code,
                    'city' => $city,
                    'cardtype' => '',
                    'type' => 'TEL',
                    'realPhone' => $realPhone,
                ),
            );

            return $ret;
        }
        //处理号码
        if (substr($phone, 0, 3) == '+86') {
            $phone = substr($phone, 3);
        }
        if (substr($phone, 0, 2) == '86') {
            $phone = substr($phone, 2);
        }
        if (substr($phone, 0, 1) == 0) {
            $phone = substr($phone, 1);
        }
        //号段取前7位进行比较
        $num = substr($phone, 0, 7);
        $realPhone = $phone;

        //查询区号对应的城市信息
        $info = $db->fetchAssoc(
            "SELECT num,code,city,cardtype FROM location WHERE num = :num ",
            array('num' => $num)
        );

        //查询不到则通过接口获取
        if (empty($info)) {
            $result = $this->fetchInfoFromUrl($phone);
            //接口中也未获取到结果则返回失败
            if ($result === false) {
                $ret = array(
                    'code' => 402,
                    'message' => '未获取到相关的归属地信息',
                );

                return $ret;
            } else {
                $result['realPhone'] = $realPhone;
                $result['type'] = 'MOBILE';
                $ret = array(
                    'code' => 200,
                    'message' => 'ok',
                    'data' => $result,
                );

                //将结果保存到数据库中
                try {
                    $pre = $db->prepare("INSERT INTO location(num,city,cardtype,code) VALUES (:num,:city,:cardtype,:code)");
                    $res = $pre->execute(array(
                        ':num' => empty($result['num']) ? '' : $result['num'],
                        ':city' => empty($result['city']) ? '' : $result['city'],
                        ':cardtype' => empty($result['cardtype']) ? '' : $result['cardtype'],
                        ':code' => empty($result['code']) ? '' : $result['code'],
                    ));
                    if ($res) {
                        $logger->info('添加号码【'.$phone.'】归属地信息到数据库成功');
                    } else {
                        $logger->warning('添加号码【'.$phone.'】归属地信息到数据库失败');
                    }
                } catch (\Exception $e) {
                    $logger->warning(sprintf(
                        '添加号码【%s】归属地信息到数据库失败， 错误为【%s】',
                        $phone,
                        $e->getMessage()
                    ));
                }

                return $ret;
            }
        } else {
            $logger->info('从数据库中获取号码【'.$phone.'】成功，返回结果为'.json_encode($info));
            $info['realPhone'] = $realPhone;
            $info['type'] = 'MOBILE';
            $ret = array(
                'code' => 200,
                'message' => 'ok',
                'data' => $info,
            );

            return $ret;
        }
    }

    /**
     * 检查电话号码是否是移动电话
     *
     * @param string $phone 电话号码
     *
     * @return bool
     */
    public function checkPhoneIsMobileOrNot($phone)
    {
        if (empty($phone)) {
            return false;
        }

        if (preg_match('/^(\+)?(86)?(0)?1[3-9]\d{9}$/', $phone)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 从接口获取
     *
     * @param $phone
     *
     * @return array|bool
     */
    private function fetchInfoFromUrl($phone)
    {
        if (empty($phone)) {
            return false;
        }
        /** @var \Monolog\Logger $logger */
        $logger = $this->container->get("logger");
        $apiUrls = $this->container->getParameter('outer_api_url');
        $urls = empty($apiUrls) ? array() : $apiUrls;
        if (empty($urls)) {
            $logger->error('未设置获取归属地接口地址');

            return false;
        }

        $info = array();
        foreach ($urls as $vendor => $url) {
            switch ($vendor) {
                case 'icsoc':
                    $ch = curl_init();
                    $url .= '?phone='.$phone;
                    curl_setopt($ch, CURLOPT_URL, $url);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($ch, CURLOPT_TIMEOUT, 2);

                    $result = curl_exec($ch);
                    $jsonResult = json_decode($result, true);
                    if (json_last_error() === JSON_ERROR_NONE) {
                        $code = empty($jsonResult['code']) ? '' : $jsonResult['code'];
                        $message = empty($jsonResult['message']) ? '' : $jsonResult['message'];
                        $data = empty($jsonResult['data']) ? array() : $jsonResult['data'];

                        //获取成功
                        if ($code == 200) {
                            $info = $data;
                            $logger->info('通过【'.$vendor.'】接口查询【'.$phone.'】归属地成功，返回结果为'.$result);
                        } else {
                            $logger->warning('获取【'.$vendor.'】接口查询号码【'.$phone.'】归属地失败，错误代码为【'.$message.'】');
                        }
                    } else {
                        $logger->warning('通过【'.$vendor.'】接口查询【'.$phone.'】归属地失败，返回结果为'.$result);
                    }
                    curl_close($ch);
                    break;
                default:
                    break;
            }
            //只要有一个接口查到数据就返回，无需访问其他接口，否则继续访问
            if (!empty($info)) {
                return $info;
            } else {
                continue;
            }
        }

        return false;
    }
}
